// figuras.cpp: implementation of the figuras class.
//
//////////////////////////////////////////////////////////////////////

#include "figuras.h"



//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

figuras::figuras()
{
	x0 = y0 = x1 = y1 = 0;
	dx = dy = ix = iy = 0;
	e = 0;
	radio = 0;
}

figuras::~figuras()
{

}

/*-------------------------------------------------------*/

// RECTAS

void figuras::bhmRecta1_7() {
  	
	int y = y0;
	int x = x0;

	e = dy > 0 ? iy - dx : iy + dx; // 1 o 7

	for ( x = x0; x <= x1; x++)	{
		glVertex2i(x,y);
		e += dy;
		if (dy > 0) {		// 1
			if (e > 0) {
				y++;
				e -= dx;
				}
			}
		else {				// 7
			if (e < 0) {
				y--;
				e += dx;
				}
			}
		}  
	}

/*--------------------------------------------------------*/
void figuras::bhmRecta3_5() {

	int y = y0;
	int x = x0;
  	
	e = dx > 0 ? ix + dy : ix - dy;	// 3 o 5

	for ( y = y0; y >= y1; y--)	{
		glVertex2i(x,y);
		e += dx;
		if (dx > 0) {
			if (e > 0) {	// 3
				x++;
				e += dy;
				}
			}
		else {				// 5
			if (e < 0) {
				x--;
				e -= dy;
				}
			} 
		}
	}
/*---------------------------------------------------------*/
void figuras::bhmRecta(int X0, int Y0, int X1, int Y1) {	
	
	x0 = X0;
	y0 = Y0;
	x1 = X1;
	y1 = Y1;

	dx = x1 - x0;
	dy = y1 - y0;
	ix = 2 * dx;
	iy = 2 * dy;
	
	if (dx < dy) {
		swapPuntos();
		dx = -dx;
		dy = -dy;
		ix = -ix;
		iy = -iy;
		}

	if ( (dy <= -dx) || (dx < 0) )
		bhmRecta3_5();
	else
		bhmRecta1_7();
	}

/*---------------------------------------------------------*/
void figuras::swapPuntos() {
	int tmpX;
	int tmpY;
	
	tmpX = x0;
	tmpY = y0;
	x0 = x1;
	y0 = y1;
	x1 = tmpX;
	y1 = tmpY;

	}


void figuras::bhmScanLineInit()
{
 
// maximo y minimo 
  int j;
  for (j = 0; j< max;j++)
  {
	  maxx[j] = menosinfinito;
	  minx[j] = masinfinito;
  }  

}

void figuras::bhmScanLine1_7() {
  	
	int y = y0;
	int x = x0;

	e = dy > 0 ? iy - dx : iy + dx; // 1 o 7

	for ( x = x0; x <= x1; x++)	{
		if (x > maxx[y]) {maxx[y] = x;}
		if (x < minx[y]) {minx[y] = x;}
		glVertex2i(x,y);
		e += dy;
		if (dy > 0) {		// 1
			if (e > 0) {
				y++;
				e -= dx;
				}
			}
		else {				// 7
			if (e < 0) {
				y--;
				e += dx;
				}
			}
		}  
	}

/*--------------------------------------------------------*/
void figuras::bhmScanLine3_5() {

	int y = y0;
	int x = x0;
  	
	e = dx > 0 ? ix + dy : ix - dy;	// 3 o 5

	for ( y = y0; y >= y1; y--)	{
		if (x > maxx[y]) {maxx[y] = x;}
		if (x < minx[y]) {minx[y] = x;}
		e += dx;
		if (dx > 0) {
			if (e > 0) {	// 3
				x++;
				e += dy;
				}
			}
		else {				// 5
			if (e < 0) {
				x--;
				e -= dy;
				}
			} 
		}
	}
/*---------------------------------------------------------*/
void figuras::bhmScanLine(int X0, int Y0, int X1, int Y1) {	
	
	x0 = X0;
	y0 = Y0;
	x1 = X1;
	y1 = Y1;

	dx = x1 - x0;
	dy = y1 - y0;
	ix = 2 * dx;
	iy = 2 * dy;
	
	if (dx <= dy) {
		swapPuntos();
		dx = -dx;
		dy = -dy;
		ix = -ix;
		iy = -iy;
		}

	if ( (dy < -dx) || (dx < 0) )
		bhmScanLine3_5();
	else
		bhmScanLine1_7();
	}


void figuras::bhmScanLineRellenar()
{
int j;
// grafico linea 
  for (j = 0; j< max;j++)
  {
	  if ( (maxx[j] != menosinfinito) && (minx[j] != masinfinito) )
	  {
		  bhmRecta(minx[j],j,maxx[j],j);
      }
  }  

}


// CIRCULOS

void figuras::bhmCirculo(float r, int X0, int Y0) 
{
	int x = r;
	int y = 0;
	
	x0 = X0;
	y0 = Y0;
	radio = r;

	e = 0;
	while ( y < x)
	{
		glVertex2i(x + x0,y + y0);
        glVertex2i(y + x0,x + y0);

        glVertex2i(-x + x0,y + y0);
        glVertex2i(-y + x0,x + y0);

        glVertex2i(x + x0,-y + y0);
        glVertex2i(y + x0,-x + y0);

		glVertex2i(-x + x0,-y + y0);
        glVertex2i(-y + x0,-x + y0);

        e += ((2*y) + 1);
		y++;

        if ( (2*e) > ( (2 * x) - 1) ) 
		{
			x--;
			e+= ( 1 -  (2*x) );

		}

	}

}

void figuras::bhmCirculoRellenar()
{
	float r = radio;
	for(float i = radio; i>=0; i= i - 1) {
		bhmCirculo(i, x0, y0);
	
	}

}

// POLIGONOS

// inserta al final del array de puntos
void figuras::insertarPunto(int x, int y) {
	tPunto rPunto;
	rPunto.posX = x;
	rPunto.posY = y;
	aPuntos.push_back(rPunto);

}

// quita el ultimo punto del array 
void figuras::quitarPunto() {
	aPuntos.pop_back();

}

void figuras::clearPuntos() {
	aPuntos.clear();
}


void figuras::bhmPoligono() {
		
	int nCantPuntos = aPuntos.size();

	for (int i= 0; i < nCantPuntos-1; i++) 
	{
		bhmRecta( aPuntos[i].posX, aPuntos[i].posY, aPuntos[i+1].posX, aPuntos[i+1].posY);	
	}
	// ahora unimos el primer y el ultimo  punto
	bhmRecta(aPuntos[nCantPuntos-1].posX, aPuntos[nCantPuntos-1].posY, aPuntos[0].posX, aPuntos[0].posY );	

}

//	esta funcion solo rellena poligonos convexos, 
//	de no ser asi no garantiza el rellenado del poligono como se esperaria
void figuras::bhmPoligonoRellenar() {
		
	int nCantPuntos = aPuntos.size();
	
	if (nCantPuntos >= 3) 
	{
		bhmScanLineInit();

		for (int i= 0; i < nCantPuntos-1; i++) 
		{
			bhmScanLine( aPuntos[i].posX, aPuntos[i].posY, aPuntos[i+1].posX, aPuntos[i+1].posY);	
		}
		// ahora unimos el primer y el ultimo  punto
		bhmScanLine(aPuntos[nCantPuntos-1].posX, aPuntos[nCantPuntos-1].posY, aPuntos[0].posX, aPuntos[0].posY );	
	
		bhmScanLineRellenar();
	}
}